package de.fhd.pms.dao;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Before;
import org.springframework.context.ApplicationContext;

import de.fhd.pms.model.Action;
import de.fhd.pms.model.Tour;
import de.fhd.pms.model.User;
import de.fhd.pms.model.UsersTour;

import org.junit.Test;
/**
 * A Test class (Junit) for {@link UsersTourDao} to find out if all Methods defined in UsersTourDao are working fine.
 * This class uses a special test-database "hitchtest".
 */
public class UsersTourDaoTest extends AbstractDataAccessTest {

	private static final Log log = LogFactory.getLog(UserDaoTest.class);

	private static final String[] configFiles = new String[] { "test-application-context.xml" };

	private ApplicationContext ctx = null;

	private String tableName = "userstour";
	private String[] tables = { tableName };

	User user = null;
	Tour tour = null;
	Action action = null;
	UsersTour usersTour = null;

	Date birthdate = null;

	UserDao userDao = null;
	TourDao tourDao = null;
	ActionDao actionDao = null;
	UsersTourDao usersTourDao = null;
	
	/**Set UsersTourDao
	 @param usersTourDao
	  */
	public void setUsersTourDao(UsersTourDao usersTourDao) {
		this.usersTourDao = usersTourDao;
	}
	/**Set TourDao
	 @param tourDao
	  */
	public void setTourDao(TourDao tourDao) {
		this.tourDao = tourDao;
	}
	/**Set UserDao
	 @param userDao
	  */
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	/**Set ActionDao
	 @param actionDao
	  */
	public void setActionDao(ActionDao actionDao) {
		this.actionDao = actionDao;
	}
	/**Setup Configuration
	  */
	@Before
	public void onSetUp() {
		Date date = new Date();

		user = new User();

		birthdate = date;

		user.setEnabled(1);
		user.setBirthdate(birthdate);
		user.setGender(1);
		user.setEmail("test@test.lv");
		user.setUsername("andreas");
		user.setPassword("qwER12!@");
		user.setPasswordConfirm("qwER12!@");
		user.setName("Andreas");
		user.setLastname("Janow");

		action = new Action();
		action.setDescription("Some small description");
		action.setEnd_date(date);
		action.setEnd_hours(11);
		action.setEnd_minutes(10);
		action.setName("Action name");
		action.setStart_date(date);
		action.setStart_hours(10);
		action.setStart_minutes(10);
		action.setUser(user);

		tour = new Tour();
		tour.setAction(action);
		tour.setUser(user);
		tour.setEnd_hours(10);
		tour.setEnd_minutes(10);
		tour.setMax_member_count(2);
		tour.setMin_member_count(1);
		tour.setDescription("description");
		tour.setStart_date(date);
		tour.setEnd_hours(10);
		tour.setEnd_minutes(10);

		usersTour = new UsersTour();
	}
	/**
	 * A Test to find out if a {@link Tour} can be created depending on {@link User} and {@link Action}.
	 */
	@Test
	public void testGetUsersTourByTour() {
		log.info(user);

		userDao.save(user);

		User tmpUser = userDao.findByUsername(user.getUsername());

		action.setUser(tmpUser);
		actionDao.save(action);

		tour.setUser(tmpUser);
		tour.setAction(action);
		tourDao.save(tour);

		Integer userId = user.getId();
		Integer tourId = tour.getId();

		log.info("tour Id" + tourId);
		log.info("user Id" + userId);
		usersTour.setTourId(tourId);

		usersTour.setUserId(userId);
		usersTourDao.save(usersTour);
		UsersTour tmpUsersTour = usersTourDao.searchByUserAndTour(tour, tmpUser);
		

		List<UsersTour> allUsersTours = usersTourDao.getUsersTourByTour(tour);

		if (allUsersTours == null) {
			Assert.fail();
		}

		for (UsersTour aut : allUsersTours) {
			if(!aut.equals(tmpUsersTour)){
				log.info("FRFREEGRGBTR");
			} else {
				log.info("EQ");
			}
			log.info("tmpUsersTour - tourId: " + tmpUsersTour.getTourId());
			log.info("tmpUsersTour - userId: " + tmpUsersTour.getUserId());
			log.info("tmpUsersTour - usersTourId: " + tmpUsersTour.getUserTourId());
						
			log.info("aut - tourId: " + aut.getTourId());
			log.info("aut - userId: " + aut.getUserId());
			log.info("aut - usersTourId: " + aut.getUserTourId() );
			
			
			assertEquals(tmpUsersTour.getTourId(), aut.getTourId());
			assertEquals(tmpUsersTour.getUserId(), aut.getUserId());
			assertEquals(tmpUsersTour.getUserTourId(), aut.getUserTourId());
			
		}

		
		try {
			usersTourDao.delete(tmpUsersTour);
		} catch (DaoException e) {
			Assert.fail();
		}	
		try {
			tourDao.delete(tour, tmpUser);
		} catch (DaoException e) {
			Assert.fail();
		}
		actionDao.delete(action);
		userDao.delete(tmpUser);
	}

	/**
	 * Test to find out that user registration to tour in normal case is functioning.
	 * */
	@Test
	public void testIsUserRegisteredToTour(){
		
		userDao.save(user);
		actionDao.save(action);
		
		User tmpUser = userDao.findByUsername(user.getUsername());
		
		tour.setUser(tmpUser);
		tourDao.save(tour);
		Set<Tour> tourList = tourDao.findByUser(tmpUser);
		Tour tmpTour = null;
		for (Tour t : tourList) {
			tmpTour = t;
			break;
		}
		
		Integer tourId = tmpTour.getId();
		usersTour.setTourId(tourId);
		Integer userId = tmpUser.getId();
		usersTour.setUserId(userId);
		usersTourDao.save(usersTour);
		
		List<UsersTour> usersTourList = usersTourDao.getUsersTourByTour(tmpTour);
		UsersTour tmpUsersTour = null;
		for (UsersTour t : usersTourList) {
			tmpUsersTour = t;
			break;
		}
		
		
		boolean isRegistered = usersTourDao.isUserRegisteredToTour(tmpTour, tmpUser);
		log.info("tmpTour: " + tmpTour.getId());
		log.info("tmpUser: " + tmpUser.getId());
		log.info("isRegistered: " + isRegistered);
		assertEquals(true, isRegistered);
		
		try {
			usersTourDao.delete(tmpUsersTour);
		} catch (DaoException e) {
			Assert.fail();
		}	
		try {
			tourDao.delete(tour, tmpUser);
		} catch (DaoException e) {
			Assert.fail();
		}
		actionDao.delete(action);
		userDao.delete(tmpUser);
		
	}
	
	/**
	 * Test to find out that in normal usage case record of users to tour is saved to the data base.
	 * */
	@Test
	public void testSave(){
		userDao.save(user);
		actionDao.save(action);
		
		User tmpUser = userDao.findByUsername(user.getUsername());
		
		tour.setUser(tmpUser);
		tourDao.save(tour);
		Set<Tour> tourList = tourDao.findByUser(tmpUser);
		Tour tmpTour = null;
		for (Tour t : tourList) {
			tmpTour = t;
			break;
		}
		
		Integer tourId = tmpTour.getId();
		usersTour.setTourId(tourId);
		Integer userId = tmpUser.getId();
		usersTour.setUserId(userId);
		usersTourDao.save(usersTour);
		
		List<UsersTour> usersTourList = usersTourDao.getUsersTourByTour(tmpTour);
		UsersTour tmpUsersTour = null;
		for (UsersTour t : usersTourList) {

			assertEquals(usersTour.getTourId(), t.getTourId());
			assertEquals(usersTour.getUserId(), t.getUserId());
			tmpUsersTour = t;
		}
		
		try {
			usersTourDao.delete(tmpUsersTour);
		} catch (DaoException e) {
			Assert.fail();
		}	
		try {
			tourDao.delete(tour, tmpUser);
		} catch (DaoException e) {
			Assert.fail();
		}
		actionDao.delete(action);
		userDao.delete(tmpUser);
	}
	
	/**
	 * Test to find out that in normal usage case search by user and tour in the database table userstour occurs.
	 * */
	@Test
	public void testSearchByUserAndTour(){
		userDao.save(user);
		actionDao.save(action);
		
		User tmpUser = userDao.findByUsername(user.getUsername());
		
		tour.setUser(tmpUser);
		tourDao.save(tour);
		Set<Tour> tourList = tourDao.findByUser(tmpUser);
		Tour tmpTour = null;
		for (Tour t : tourList) {
			tmpTour = t;
			break;
		}
		
		Integer tourId = tmpTour.getId();
		usersTour.setTourId(tourId);
		Integer userId = tmpUser.getId();
		usersTour.setUserId(userId);
		usersTourDao.save(usersTour);
		
		List<UsersTour> usersTourList = usersTourDao.getUsersTourByTour(tmpTour);
		UsersTour tmpUsersTour = null;
		for (UsersTour t : usersTourList) {
			tmpUsersTour = t;
			break;
		}
		
		UsersTour find = usersTourDao.searchByUserAndTour(tmpTour, tmpUser);
		assertEquals(tmpUsersTour.getTourId(), find.getTourId());
		assertEquals(tmpUsersTour.getUserId(), find.getUserId());
		assertEquals(tmpUsersTour.getTourId(), find.getUserTourId());
		
		try {
			usersTourDao.delete(tmpUsersTour);
		} catch (DaoException e) {
			Assert.fail();
		}	
		try {
			tourDao.delete(tour, tmpUser);
		} catch (DaoException e) {
			Assert.fail();
		}
		actionDao.delete(action);
		userDao.delete(tmpUser);
	}
	
	/** Test to find out that in normal usage case records are deleted from the data base table userstour 
	 */
	@Test
	public void testDelete(){
		
		userDao.save(user);
		actionDao.save(action);
		
		User tmpUser = userDao.findByUsername(user.getUsername());
		
		tour.setUser(tmpUser);
		tour.setAction(action);
		tourDao.save(tour);
		
		Set<Tour> tourList = tourDao.findByUser(tmpUser);
		Tour tmpTour = null;
		for (Tour t : tourList) {
			tmpTour = t;
			break;
		}
		usersTour = new UsersTour();
		Integer tourId = tmpTour.getId();
		usersTour.setTourId(tourId);
		Integer userId = tmpUser.getId();
		usersTour.setUserId(userId);
		log.info("DDD uid" + userId);
		log.info("DDD ut" + usersTour);
		usersTourDao.save(usersTour);
		log.info("DDD");
		
		List<UsersTour> usersTourList = usersTourDao.getUsersTourByTour(tmpTour);
		UsersTour tmpUsersTour = null;
		for (UsersTour t : usersTourList) {
			tmpUsersTour = t;
			break;
		}
		
		try {
			usersTourDao.delete(tmpUsersTour);
		} catch (DaoException e) {
			Assert.fail();
		}	
		try {
			tourDao.delete(tour, tmpUser);
		} catch (DaoException e) {
			
		}
		actionDao.delete(action);
		userDao.delete(tmpUser);
		
		usersTourList = usersTourDao.getUsersTourByTour(tmpTour);
		
		log.info("usersTourList: " + usersTourList);
		log.info("amount: " + usersTourList.size());
		
		assertEquals(0, usersTourList.size());
	}
	
}
